home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 Extra Demos / User Contributions / ButtonBreakOut ƒ / SpritePersistence / SpritePersistence.c next >
Encoding:
Text File  |  1999-01-11  |  9.6 KB  |  299 lines  |  [TEXT/CWIE]

  1. // SpritePersistence.c
  2. // -------------------
  3. // v2.3  
  4. // (Note: uses DataPersistence services)
  5. // feedback: macdev@tnuctip.com
  6.  
  7. #include     "SWIncludes.h"
  8.  
  9. #include     "DataPersistence.h"
  10.  
  11. #define        OWNER
  12. #include     "SpritePersistence.h"
  13. #undef        OWNER
  14.  
  15.  
  16.  
  17. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  18. //                        THESE ROUTINES MAY BE MODIFIED TO ADAPT TO YOUR OWN DATA
  19. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  20.  
  21. #pragma mark •————Customizable————
  22.  
  23.  
  24. ///--------------------------------------------------------------------------------------
  25. // This is called before writing a record to disk. You just have to fill the record.
  26. ///--------------------------------------------------------------------------------------
  27.  
  28. void SWGCopyFromSpriteToRecord (SpritePtr spriteP, tSpriteSaveHandle recordHandle)
  29. {
  30.     (*recordHandle)->hz = spriteP->destFrameRect.left;
  31.     (*recordHandle)->vt = spriteP->destFrameRect.top;
  32.     (*recordHandle)->userDataExample = spriteP->userData;
  33. }
  34.  
  35.  
  36. ///--------------------------------------------------------------------------------------
  37. // This is called after reading a record from disk. You update the sprite using the data. 
  38. // Don't forget to call the appropriate SW routines to update the sprites' position, 
  39. // deltas, whatever you have changed.
  40. ///--------------------------------------------------------------------------------------
  41.  
  42. void SWGCopyFromRecordToSprite (tSpriteSaveHandle recordHandle, SpritePtr spriteP)
  43. {
  44.     SWMoveSprite (spriteP, (*recordHandle)->hz, (*recordHandle)->vt);
  45.     spriteP->userData = (*recordHandle)->userDataExample;
  46. }
  47.  
  48.  
  49. ///--------------------------------------------------------------------------------------
  50. // This is where the resource ID for each sprite is computed. It is placed in the <customizable
  51. // routines> section because you might want a different numbering scheme (e.g. you might want
  52. // several copies of the same sprites, at different times, or whatever..) That's also 
  53. // why spriteP is provided: you might want to use it's data in your numbering scheme.
  54. ///--------------------------------------------------------------------------------------
  55.  
  56. SInt16 SWGComputeResourceID (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
  57. {
  58.     #pragma unused (spriteP)
  59.  
  60.     return layerNum * kMaxSpritesInOneLayer + spriteNum;
  61. }
  62.  
  63.  
  64. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  65. //                                    PUBLIC : called by your app
  66. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  67.  
  68. #pragma mark •—————Public—————
  69.  
  70. ///--------------------------------------------------------------------------------------
  71. // All layers in the world will be scanned and written out or read in.
  72. // File is automatically opened and then closed (if user hasn't opened it before calling).
  73. //
  74. // There are interface macros for Save and Load (look inside SpritePersistence.h) :
  75. //         #define        SWGSaveSpritesInAllLayers(x)    SWGDoSpritesInAllLayers (x, true)
  76. //         #define        SWGLoadSpritesInAllLayers(x)    SWGDoSpritesInAllLayers (x, false)
  77. // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
  78. ///--------------------------------------------------------------------------------------
  79.  
  80. OSErr SWGDoSpritesInAllLayers (SpriteWorldPtr spriteWorldP, Boolean write)
  81. {
  82.     OSErr                err;
  83.     SpriteLayerPtr         spriteLayerP;
  84.     Boolean                fileWasOpenedHere;
  85.  
  86.     fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
  87.  
  88.     spriteLayerP = spriteWorldP->headSpriteLayerP;    
  89.  
  90.     while (spriteLayerP != nil)
  91.     {
  92.         err = SWGDoSpritesInLayer (spriteLayerP, write);
  93.         if (err != noErr)
  94.             break;
  95.  
  96.         spriteLayerP = spriteLayerP->nextSpriteLayerP;
  97.     }
  98.  
  99.     if (fileWasOpenedHere)
  100.         SWGClosePersistenceFile ();
  101.  
  102.     return err;
  103. }
  104.  
  105.  
  106. ///--------------------------------------------------------------------------------------
  107. // All sprites in this layer will be scanned and written out or read in, through a hook to
  108. // SWGCopyFromSpriteToRecord or SWGCopyFromRecordToSprite.
  109. // The file is automatically opened and then closed (if user hasn't opened it before calling).
  110. //
  111. // There are interface macros for Save and Load (look inside SpritePersistence.h) :
  112. //         #define        SWGSaveSpritesInLayer(x)        SWGDoSpritesInLayer (x, true)
  113. //         #define        SWGLoadSpritesInLayer(x)        SWGDoSpritesInLayer (x, false)
  114. // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
  115. ///--------------------------------------------------------------------------------------
  116.  
  117. OSErr SWGDoSpritesInLayer (SpriteLayerPtr spriteLayerP, Boolean write)
  118. {
  119.     SInt16            layerNum;
  120.     SInt16            spriteNum        = 0;
  121.     OSErr            err;
  122.     SpritePtr         curSpriteP        = nil;
  123.     Boolean            fileWasOpenedHere;
  124.  
  125.     fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
  126.  
  127.     layerNum = SWGGetLayerNumber (spriteLayerP);
  128.  
  129.     while ((curSpriteP = SWGetNextSprite (spriteLayerP, curSpriteP)) != nil)
  130.     {
  131.         spriteNum++;                                            // numbered [1..x]
  132.         err = SWGDoSingleSprite (layerNum, spriteNum, curSpriteP, write);
  133.         if (err != noErr)
  134.             break;
  135.     }
  136.  
  137.     if (fileWasOpenedHere)
  138.         SWGClosePersistenceFile ();
  139.  
  140.     return err;
  141. }
  142.  
  143.  
  144. ///--------------------------------------------------------------------------------------
  145. // Single sprite read/write. 
  146. //
  147. // There are interface macros for Save and Load (look inside SpritePersistence.h) :
  148. //    #define    SWGSaveSingleSprite (x,y,z)        SWGDoSingleSprite (x, y, z, true)
  149. //    #define    SWGLoadSingleSprite (x,y,z)        SWGDoSingleSprite (x, y, z, false)
  150. // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
  151. ///--------------------------------------------------------------------------------------
  152.  
  153. OSErr SWGDoSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP, Boolean write)
  154. {
  155.     OSErr            err;
  156.     Boolean            fileWasOpenedHere;
  157.  
  158.     fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
  159.  
  160.     if (write)
  161.         err = _SWGSaveSingleSprite (layerNum, spriteNum, spriteP);
  162.     else
  163.         err = _SWGLoadSingleSprite (layerNum, spriteNum, spriteP);
  164.  
  165.     if (fileWasOpenedHere)
  166.         SWGClosePersistenceFile ();
  167.  
  168.     return err;
  169. }
  170.  
  171.  
  172. ///--------------------------------------------------------------------------------------
  173. // Return a logical number in [1..x] based on layer ordering. 
  174. // Quickly scans the layer links, counting the number of steps needed to
  175. // reach the head of list.
  176. ///--------------------------------------------------------------------------------------
  177.  
  178. SInt16 SWGGetLayerNumber (SpriteLayerPtr spriteLayerP)
  179. {
  180.     SInt16    num            = 0;
  181.  
  182.     do
  183.     {
  184.         num++;
  185.         spriteLayerP = spriteLayerP->prevSpriteLayerP;
  186.     }
  187.         while (spriteLayerP != nil);
  188.  
  189.  
  190.     return num;
  191. }
  192.  
  193.  
  194. ///--------------------------------------------------------------------------------------
  195. // Return a logical number in [1..x] based on sprite ordering. 
  196. // Quickly scans the sprite links, counting the number of steps needed to
  197. // reach the head of list.
  198. ///--------------------------------------------------------------------------------------
  199.  
  200. SInt16 SWGGetSpriteNumber (SpritePtr spriteP)
  201. {
  202.     SInt16    num            = 0;
  203.  
  204.     do
  205.     {
  206.         num++;
  207.         spriteP = spriteP->prevSpriteP;
  208.     }
  209.         while (spriteP != nil);
  210.  
  211.  
  212.     return num;
  213. }
  214.  
  215.  
  216. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  217. //                                    PRIVATE : internal use only
  218. // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
  219.  
  220. #pragma mark •—————Private—————
  221.  
  222. ///--------------------------------------------------------------------------------------
  223. // Does the actual saving job for a sprite
  224. ///--------------------------------------------------------------------------------------
  225.  
  226. OSErr _SWGSaveSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
  227. {
  228.     OSErr                err                    = noErr;
  229.  
  230.     if (gSWGBufferHandle == nil)
  231.     {
  232.         err = _SWGCreateBufferHandle ();
  233.         if (gSWGBufferHandle == nil)                                // allocation failed, abort operation
  234.             return err;
  235.     }
  236.  
  237.     // #MOD?
  238.     // Read the rez before writing (if not found, create it with zeroed data);
  239.     // this allows the SWGCopyFromSpriteToRecord routine to replace data partially,
  240.     // if the user so wishes.
  241.  
  242.     HLock (gSWGBufferHandle);
  243.     SWGCopyFromSpriteToRecord (spriteP, (tSpriteSaveHandle) gSWGBufferHandle);
  244.     err = SWGSaveRecord (*gSWGBufferHandle, sizeof (tSpriteSaveRec), SWGComputeResourceID (layerNum, spriteNum, spriteP));
  245.     HUnlock (gSWGBufferHandle);
  246.  
  247.     return err;
  248. }
  249.  
  250.  
  251.  
  252. ///--------------------------------------------------------------------------------------
  253. // Does the actual loading job for a sprite
  254. ///--------------------------------------------------------------------------------------
  255.  
  256. OSErr _SWGLoadSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
  257. {
  258.     OSErr                err                = noErr;
  259.  
  260.     if (gSWGBufferHandle == nil)
  261.     {
  262.         err = _SWGCreateBufferHandle ();
  263.         if (gSWGBufferHandle == nil)                                // allocation failed, abort operation
  264.             return err;
  265.     }
  266.  
  267.     HLock (gSWGBufferHandle);
  268.  
  269.     err = SWGLoadRecord (*gSWGBufferHandle, sizeof (tSpriteSaveRec), SWGComputeResourceID (layerNum, spriteNum, spriteP));
  270.  
  271.     if (err == noErr || err == kDataSizeSmallerError || err == kDataSizeBiggerError)    // accept different size
  272.         SWGCopyFromRecordToSprite ((tSpriteSaveHandle) gSWGBufferHandle, spriteP);
  273.  
  274.     HUnlock (gSWGBufferHandle);
  275.  
  276.     return err;
  277. }
  278.  
  279.  
  280. ///--------------------------------------------------------------------------------------
  281. // Allocate a single permanent handle to be used for all load/saves.
  282. ///--------------------------------------------------------------------------------------
  283.  
  284. OSErr _SWGCreateBufferHandle (void)
  285. {
  286.     OSErr        err        = noErr;
  287.  
  288.     gSWGBufferHandle = NewHandle (sizeof (tSpriteSaveRec));
  289.     if (gSWGBufferHandle == nil)
  290.     {
  291.         err = memFullErr;
  292.         SWGErrorReportingStub (err);                                // default is simply a beep
  293.     }
  294.  
  295.     return err;
  296. }
  297.  
  298. // end
  299.